#ifndef __TIMECALLBACK_CPP
#define __TIMECALLBACK_CPP

#include "common/bytearrays.h"
#include "timecallback.h"
#include "common/msghandle.h"
#include "common/msgqueue.h"
#include "common/output.h"
#include "common/usertype.h"
#include "unistd.h"

using namespace std;
struct PTS {
	time_t start;
	int second;
	int id;
	int clientindex;
	byteArrays* param;
	PTS() {param = NULL;}
};

_wserVector<PTS> tbObject;

timecallback* timecallback::m_instance = NULL;
pthread_mutex_t timecallback::m_mutex;

std::map<int, TimeoutInfo> timeoutlist;

timecallback::timecallback()
{
	pthread_mutex_init(&m_mutex,0);
	pthread_t pid;
	pthread_create(&pid,0, &tick, NULL);
}

void* timecallback::tick(void* arg)
{
	pthread_detach(pthread_self());
	int i, j;
	while (1) {
		usleep(100000);
		time_t tmt;tmt = time(NULL);
		pthread_mutex_lock(&m_mutex);
		for (i = 0;i < tbObject.size();i++) {
			if (!tbObject.check(i)) continue;
			PTS& pt = tbObject[i];
			if ((tmt-pt.start) >= pt.second) {
				if (timeoutlist.find(pt.id) != timeoutlist.end()) {
					if (timeoutlist[pt.id].recvproc == 0) {
						MsgTimeout msg;msg.timeoutid = pt.id;msg.param = *pt.param;
						WServer::MsgHandle::CreateMessage2WMain(pt.clientindex, msg);
					}
					else if (timeoutlist[pt.id].recvproc == 1) {
						MsgTimeout msg;msg.timeoutid = pt.id;msg.param = *pt.param;
						WServer::MsgHandle::CreateMessage2WMysql(pt.clientindex, msg);
					}
					else if (timeoutlist[pt.id].recvproc == 2) {
//						WServer::MsgHandle::CreateMessage2WSocket(WMSG_TIMEOUT, pt.clientindex, ba);
					}
					else if (timeoutlist[pt.id].recvproc == 4) {
//						WServer::MsgHandle::CreateMessage2Simulator(WMSG_TIMEOUT, pt.clientindex, ba);
					}
				}
				tbObject.erase(i+1);
			}
		}
		pthread_mutex_unlock(&m_mutex);
	}
}

void timecallback::addCallBack(int clientindex, int timeID, byteArrays param, int second)
{
	pthread_mutex_lock(&m_mutex);
	PTS pt;
	pt.id = timeID;
	pt.clientindex = clientindex;
	pt.second = second;
	pt.start = time(NULL);
	pt.param = new byteArrays(param);
	tbObject.push_back(pt);
	if (timeID != TIMER_SAVEDATA && timeID != TIMER_SYNCPOS) wserPrintMsg("addCallBack. client:%d id:%d interval:%d\n", clientindex, timeID, second);
	pthread_mutex_unlock(&m_mutex);
}

void timecallback::cancelCallBackPlayer(int clientindex)
{
	pthread_mutex_lock(&m_mutex);
	for (int i = 0;i < tbObject.size();i++) {
		if (!tbObject.check(i)) continue;
		if (tbObject[i].clientindex == clientindex) {
			tbObject.erase(i+1);
		}
	}
	pthread_mutex_unlock(&m_mutex);
}

int timecallback::getCallbackRemain(int clientindex, int timeID)
{
	int remain = 0;time_t tmt;tmt = time(NULL);
	for (int i = 0;i < tbObject.size();i++) {
		if (!tbObject.check(i)) continue;
		if (tbObject[i].clientindex == clientindex && tbObject[i].id == timeID) {
			remain = tbObject[i].start+tbObject[i].second-tmt;
			break;
		}
	}
	return remain;
}

void timecallback::cancelCallBack(int clientindex, int timeID)
{
	pthread_mutex_lock(&m_mutex);
	for (int i = 0;i < tbObject.size();i++) {
		if (!tbObject.check(i)) continue;
		if (tbObject[i].clientindex == clientindex && tbObject[i].id == timeID) tbObject.erase(i+1);
	}
	pthread_mutex_unlock(&m_mutex);
}

timecallback::~timecallback()
{
	pthread_mutex_destroy(&m_mutex);
}

timecallback* timecallback::instance()
{
	if (!m_instance) {
		m_instance = new timecallback();
		tbObject.resize(1000);
	}
	return m_instance;
}

void addCallback(int clientindex, int timeID, byteArrays param, int second)
{
	if (timeoutlist.find(timeID) == timeoutlist.end()) return;
	timecallback::instance()->addCallBack(clientindex, timeID, param, second);
}
void addCallback(int clientindex, int timeID, byteArrays param)
{
	if (timeoutlist.find(timeID) == timeoutlist.end()) return;
	timecallback::instance()->addCallBack(clientindex, timeID, param, timeoutlist[timeID].interval);
}
void addCallback(int clientindex, int timeID)
{
	if (timeoutlist.find(timeID) == timeoutlist.end()) return;
	timecallback::instance()->addCallBack(clientindex, timeID, blankba, timeoutlist[timeID].interval);
}
void cancelCallBack(int clientindex, int timeID)
{
	if (timeoutlist.find(timeID) == timeoutlist.end()) return;
	timecallback::instance()->cancelCallBack(clientindex, timeID);
}
void cancelCallBackPlayer(int clientindex)
{
	timecallback::instance()->cancelCallBackPlayer(clientindex);
}
int getCallbackRemain(int clientindex, int timeID)
{
	if (timeoutlist.find(timeID) == timeoutlist.end()) return -1;
	return timecallback::instance()->getCallbackRemain(clientindex, timeID);
}

#endif  //__TIMECALLBACK_CPP